package gbench.appdemo.mall.erp.report;

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import gbench.common.fs.FileSystem;
import gbench.common.matlib.rdd.BasePair;
import gbench.common.tree.LittleTree.Term;
import gbench.common.tree.LittleTree.TrieNode;

public class ReportEngine {
    
    public ReportEngine(int n){
        this.ident_unit = n;
    }
    
    /**
     * yml 的格式解析
     * 
     * @param <U> 属性值类型
     * @param bpStream 数据流 [(String,u)]
     * @param cons   回调函数 (node,u) -> {}
     * @return TrieNode 根节点的值 为 null
     */
    public <U> TrieNode<String> yml(final Stream<BasePair<String, U>> bpStream, final BiConsumer<TrieNode<String>, U> cons) {
        final BiFunction<String,String,String> merge = (a,b)->Term.FT("$0,$1", a,b.strip());
        final Function<AtomicReference<String>, Function<String, String>> continue_line = a_pre_lines -> e -> {
            final var line = e.replaceAll("[\\\\]*$", ""); // 去除尾部的 续行 符号 \
            if (e.endsWith("\\")) { // 包含有 下一行
                a_pre_lines.updateAndGet(s -> { // 设置当前行
                    return s == null ? line : merge.apply(s, line);
                });
                return null; // 返回空值 用以表名 这是一个未完成的行，需要后面的 处理函数 给与过滤掉 这一null行。
            } else { // 没有续行符
                final var pre_lines = a_pre_lines.get(); // 获取前一行数据
                if (pre_lines == null) { // 没有前导行
                    return line;
                } else { // 包含前导行
                    a_pre_lines.set(null); // 清空前一行数据
                    return merge.apply(pre_lines, line);
                } // if
            } // if
        }; // 续行函数 continue_line
        final var lines = bpStream
            .map(e -> BasePair.bp(continue_line.apply(new AtomicReference<String>()).apply(e._1()), e._2())) // 续行计算
            .filter(bp -> bp._1() != null && !bp._1().matches("\\s*")) // 去除空行 和 null 值
            .collect(Collectors.toList());
        final var n = lines.size(); // 行数目
        final var ident_pattern = Pattern.compile("^\\s*"); // 缩进的pattern
        final var ident_entries = new TreeMap<Integer, String>(); // TreeMap 键值排序，层级结构
        final var trie = new TrieNode<String>(null,LinkedHashMap::new); // Trie 根结构
        
        for (int i = 0; i < n; i++) { // 逐行处理
            final var cell = lines.get(i);
            final var line = cell._1();
            final var matcher = ident_pattern.matcher(line); //  缩进侦测
            if (matcher.find()) { // 满足缩进格式
                final var ident = matcher.group().replaceAll("\t"," ".repeat(this.ident_unit)); // 获取缩进距离，替换 \t 为 空格
                final int n_ident = ident.length()%this.ident_unit ==0 
                        ? ident.length() // 缩进长度
                        : this.ident_unit * ((int)(ident.length()/this.ident_unit+1)); // 向上取整
                final var level = n_ident / this.ident_unit; // 当前数据项目的的层级深度, 每个tab 键名 采用 this.ident_unit 个 空格进行划分
                ident_entries.put(level, line.strip()); // 记录键值的层级
                
                if (n_ident % this.ident_unit != 0) { // 提取非格式化部分
                    System.err.println(Term.FT("error: no: $0\t level:$1\t remainder:$2 \t line:$3", 
                        i + 1, level, n_ident % this.ident_unit, line));
                } else {
                    final var flds = new LinkedList<String>(); // 字段列表
                    ident_entries.entrySet() // 获取行项目
                        .stream() // 层级的排序 按照 层级深度进行排序, 层级越深 表示 数据越细节
                        .filter(e -> e.getKey() <= level) // 提取 当前层级 以上的所有 摘要层级
                        .forEach(e -> { // 层级深度
                            flds.add(e.getValue());
                        }); // 构造字段集合 
                    final var node = trie.addParts(flds).flag(false);
                    cons.accept(node, cell._2()); // 回调函数
                } // if
            } else {
                System.err.println(line);
            } // if
        } // for
        
        return trie;
    }
    
    /**
     * yml 的格式解析
     * 
     * @param file        文件路径
     * @param start_level 开始层级，从0开始
     * @return TrieNode 根节点的值 为 null
     */
    public TrieNode<String> yml(final String file) {
        final var path = FileSystem.fileOf(file, this.getClass()); // 文件路径
        return yml(FileSystem.utf8lines(path).map(e->BasePair.bp(e, e)),(n,u)->{}); 
    }
    
    public int ident_unit = 4;

}
